package main

import (
	"crypto/rand"
	"fmt"
	"math"
)

func main() {
	const m = 50000
	var (
		c, cnt       int
		summ, summkv int
	)

	rnd := makeRandGenerator()
	for i := 0; i < m; i++ {
		cnt = 0
		c = 0
		for {
			j := rnd()
			c |= 1 << j
			cnt++

			if c == 255 {
				break
			}
		}
		summ += cnt
		summkv += cnt * cnt
	}

	mean := float64(summ) / float64(m)
	fmt.Printf("\nM: %f\n", mean)

	disp := float64(summkv) - float64(summ)*float64(summ)/float64(m)
	sigma := math.Sqrt(disp / float64(m))

	fmt.Printf("Sigma: %f\n", sigma)
	fmt.Printf("Max: %f\n", mean+3.0*sigma)
}

func makeRandGenerator() func() int {
	var (
		curr int = -1
		z    int
	)
	bytes := make([]byte, 3)
	z = threeByte(bytes)

	return func() int {
		if curr == 7 {
			z = threeByte(bytes)
			curr = -1
		}
		curr++

		return (z >> (3 * curr)) % 8
	}
}

func threeByte(bytes []byte) int {
	_, err := rand.Read(bytes)
	if err != nil {
		panic(err)
	}
	z := int(bytes[0]) + 256*int(bytes[1]) + 65536*int(bytes[2])

	return z
}
